﻿/**
 * File:   json_builder.c
 * Author: AWTK Develop Team
 * Brief:  create json
 *
 * Copyright (c) 2018 - 2020  Guangzhou ZHIYUAN Electronics Co.,Ltd.
 *
 * This program is ditokenizeributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * License file for more details.
 *
 */

/**
 * History:
 * ================================================================
 * 2020-12-27 zhang zhongji <zhangzhongji@zlg.cn> created
 *
 */
#include "json_builder.h"
#include "../3rd/cjson/cJSON.h"
#include "tkc/str.h"

typedef struct _json_ctx_t {
    cJSON* root;
    cJSON* package_array;
    cJSON* import_array;
    cJSON* interface_obj;
    cJSON* function_array;
} json_ctx_t;

ret_t converte_param_to_json(void* ctx, const void* data) {
    return_value_if_fail(ctx != NULL && data != NULL, RET_BAD_PARAMS);
    cJSON* param_array = (cJSON*)ctx;
    
    cJSON *param_obj = cJSON_CreateObject();
    cJSON_AddItemToArray(param_array, param_obj);
    param_component_t* param_component = (param_component_t*)data;

    if (param_component->tag.size > 0) {
        cJSON_AddStringToObject(param_obj , "param_tag", param_component->tag.str);
    }
    
    if (param_component->param_type.size > 0) {
        cJSON_AddStringToObject(param_obj , "param_type", param_component->param_type.str);
    }
    
    if (param_component->param_name.size > 0) {
        cJSON_AddStringToObject(param_obj , "param_name", param_component->param_name.str);
    }
    
    return RET_OK;
}

static cJSON* converte_funtion_to_json(function_component_t* function_component) {
    return_value_if_fail(function_component != NULL, NULL);
    cJSON* function_obj = cJSON_CreateObject();

    if (function_component->return_type.size > 0) {
        cJSON_AddStringToObject(function_obj , "return_type", function_component->return_type.str);
    }

    if (function_component->function_name.size > 0) {
        cJSON_AddStringToObject(function_obj , "function_name", function_component->function_name.str);
    }

    cJSON* param_array = cJSON_CreateArray();
    ret_t ret = slist_foreach(function_component->param_list, converte_param_to_json, param_array);
    cJSON_AddItemToObject(function_obj , "param_list", param_array);
    
    return function_obj;
}

void json_builder_convert_package_to_json(void* ctx, const char* package_name) {
    return_if_fail(ctx != NULL && package_name != NULL);

    json_ctx_t* json_ctx = (json_ctx_t*)ctx;
    if (json_ctx->package_array == NULL) {
        json_ctx->package_array = cJSON_CreateArray();
        cJSON_AddItemToObject(json_ctx->root, "package", json_ctx->package_array);
    }

    cJSON_AddItemToArray(json_ctx->package_array, cJSON_CreateString(package_name));
}

void json_builder_convert_import_to_json(void* ctx, const char* class_name) {
    return_if_fail(ctx != NULL && class_name != NULL);

    json_ctx_t* json_ctx = (json_ctx_t*)ctx;
    if (json_ctx->import_array == NULL) {
        json_ctx->import_array = cJSON_CreateArray();
        cJSON_AddItemToObject(json_ctx->root, "import", json_ctx->import_array);
    }

    cJSON_AddItemToArray(json_ctx->import_array, cJSON_CreateString(class_name));
}

void json_builder_convert_function_to_json(void* ctx, const char* interface_name, function_component_t* function_component) {
    return_if_fail(ctx != NULL && NULL != interface_name && function_component != NULL);

    json_ctx_t* json_ctx = (json_ctx_t*)ctx;
    if (json_ctx->interface_obj == NULL) {
        json_ctx->interface_obj = cJSON_CreateObject();
        json_ctx->function_array = cJSON_CreateArray();
        cJSON_AddStringToObject(json_ctx->interface_obj, "interface_name", interface_name);
        cJSON_AddItemToObject(json_ctx->interface_obj, "function_array", json_ctx->function_array);
        cJSON_AddItemToObject(json_ctx->root, "interface", json_ctx->interface_obj);
    }

    cJSON* function_obj = converte_funtion_to_json(function_component);
    cJSON_AddItemToArray(json_ctx->function_array, function_obj);
}

char* json_builder_get_result(builder_t* builder) {
    return_value_if_fail(builder != NULL, NULL);
    json_ctx_t* json_ctx = (json_ctx_t*)builder->ctx;

    return cJSON_Print(json_ctx->root);
}

builder_t* json_builder_create() {
    json_ctx_t* json_ctx = (json_ctx_t*)malloc(sizeof(json_ctx_t));
    json_ctx->root = cJSON_CreateObject();
    json_ctx->package_array = NULL;
    json_ctx->import_array = NULL;
    json_ctx->interface_obj = NULL;
    json_ctx->function_array = NULL;
    
    builder_t* json_builder = (builder_t*)malloc(sizeof(builder_t));
    json_builder->aidl_parser_on_package = json_builder_convert_package_to_json;
    json_builder->aidl_parser_on_import = json_builder_convert_import_to_json;
    json_builder->aidl_parser_on_function = json_builder_convert_function_to_json;
    json_builder->ctx = json_ctx;

    return json_builder;
}

ret_t json_builder_destroy(builder_t* builder) {
    return_value_if_fail(builder != NULL, RET_BAD_PARAMS);
    json_ctx_t* json_ctx = (json_ctx_t*)builder->ctx;

    cJSON_Delete(json_ctx->root);    
    free(json_ctx);
    free(builder);
    return RET_OK;
}